package com.gitee.linmt.advice;

import com.gitee.linmt.cache.CacheResultMessage;
import com.gitee.linmt.entity.Result;
import com.gitee.linmt.properties.ResultProperties;
import com.gitee.linmt.util.MessageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.annotation.Resource;

/**
 * Result 统一处理.
 *
 * @author <a href="mailto:lin-mt@outlook.com">lin-mt</a>
 */
@RestControllerAdvice
public class ResultAdvice<T> implements ResponseBodyAdvice<Result<T>> {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(ResultAdvice.class);
    
    @Resource
    private CacheResultMessage<T> cacheResultMessage;
    
    @Resource
    private ResultProperties resultProperties;
    
    @Override
    public boolean supports(final MethodParameter methodParameter,
            @NonNull final Class<? extends HttpMessageConverter<?>> aClass) {
        return Result.class.isAssignableFrom(methodParameter.getParameterType());
    }
    
    @Override
    public Result<T> beforeBodyWrite(final Result<T> result, @NonNull final MethodParameter methodParameter,
            @NonNull final MediaType mediaType, @NonNull final Class<? extends HttpMessageConverter<?>> aClass,
            @NonNull final ServerHttpRequest serverHttpRequest, @NonNull final ServerHttpResponse serverHttpResponse) {
        if (result != null) {
            if (result.getCode() != null || result.getCurdType() != null) {
                // 设置 code 对应的 message
                final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
                String lang = null;
                if (requestAttributes instanceof ServletRequestAttributes) {
                    lang = ((ServletRequestAttributes) requestAttributes).getRequest()
                            .getHeader(resultProperties.getI18nHeaderKey());
                }
                result.setMessage(cacheResultMessage.getMessageByLangAndResult(lang, result));
            } else if (result.getMessage() != null && result.getMsgParam() != null) {
                // 没有设置 code，设置了 message 和 msgParam，则格式化 message
                result.setMessage(MessageUtil.arrayFormat(result.getMessage(), result.getMsgParam()));
            }
        }
        if (resultProperties.getEnableLogger()) {
            ResultAdvice.LOGGER.info(resultProperties.getLoggerFormat(), serverHttpRequest.getURI(), serverHttpRequest.getMethod(),
                    result);
        }
        return result;
    }
}
